/*************************************************************************
 * Nuvoton Electronics Corporation confidential
 *
 * Copyright (c) 2008 by Nuvoton Electronics Corporation
 * All rights reserved
 * 
 * FILENAME
 *     nuc900_pci.c
 *
 * VERSION
 *     1.0
 *
 * DESCRIPTION
 *     NUC900 PCI library source file
 *
 * DATA STRUCTURES
 *
 *
 * FUNCTIONS
 *     PCIBusInit
 *     PCIScan
 *     PCIScanDevice
 *     PCICfg
 *
 * HISTORY
 *     2008.08.12		Created
 *
 * REMARK
 *     None
 **************************************************************************/
#ifdef ECOS
#include "stdio.h"
#include "string.h"
#include "drv_api.h"
#include "diag.h"
#include "wbtypes.h"
#include "wbio.h"
#else
#include  <stdio.h>
#include  <string.h>
#include  <stdlib.h>
#include "wblib.h"
#endif

#include  "nuc900_reg.h"
#include  "nuc900_pci.h"

#define REG_PCI_PCICTR          (PCI_BA + 0x00)
#define REG_PCI_PCISTR          (PCI_BA + 0x04)
#define REG_PCI_PCILATIMER      (PCI_BA + 0x08)
#define REG_PCI_PCICLK          (PCI_BA + 0x0c)
#define REG_PCI_PCIINTEN        (PCI_BA + 0x10)
#define REG_PCI_PCIINT          (PCI_BA + 0x14)
#define REG_PCI_CFGADDR         (PCI_BA + 0x20)
#define REG_PCI_CFGDATA         (PCI_BA + 0x24)
#define REG_PCI_PCIARB          (PCI_BA + 0x4c)
#define REG_PCI_PCIBIST         (PCI_BA + 0x50)


#ifdef ECOS
#define get_timer_ticks()   cyg_current_time()
#define sysprintf			diag_printf
#define IRQ_GROUP0			2
cyg_interrupt  pci_interrupt;
cyg_handle_t   pci_interrupt_handle;
#else
#define get_timer_ticks()	sysGetTicks(TIMER0)
#endif

#define SLOT_NUM    2
#define PCIIOBASE   0xe0000000
#define PCIMEMBASE  0xc0000000



typedef struct 
{
    UINT32 index;
    UINT32 irqnum;
    BOOL matched;
    PCI_CB_FUNC_T *g_fnPCICallback;
}  NUC900_PCI_IRQMAP;


static NUC900_PCI_IRQMAP g_pciirqmap[SLOT_NUM] = {{0x4800,1,FALSE,NULL},{0x5800,0,FALSE,NULL}};
//UINT32  g_IOAllocated=0;
//UINT32  g_MemAllocated=0;
static UINT32 g_IOLogicBaseHead = 0x400;//adjust for W9971, W9971 can only configure IO space as address 0
static UINT32 g_IOPhyBaseHead = PCIIOBASE+0x400;//adjust for W9971
static UINT32 g_MemPhyBaseHead = PCIMEMBASE;
static BOOL powerup=FALSE;
//extern void printf(char *str,...);


#ifdef ECOS

static cyg_uint32 PCI_ISR(cyg_vector_t vector, cyg_addrword_t data)
{
    UINT32 i;
    for (i=0;i<SLOT_NUM;i++)
    {    
        if (inpw(REG_AIC_GASR) & (1<<g_pciirqmap[i].irqnum))
            g_pciirqmap[i].g_fnPCICallback();
    }    

	cyg_drv_interrupt_acknowledge(IRQ_GROUP0);
	return CYG_ISR_HANDLED;
}

#else

static void PCI_ISR()
{
    UINT32 i;
    for (i=0;i<SLOT_NUM;i++)
    {    
        if (inpw(REG_AIC_GASR) & (1<<g_pciirqmap[i].irqnum))
            g_pciirqmap[i].g_fnPCICallback();
    }    
}
#endif


static VOID PCIConfig_Write(UINT32 nSlotIndex,UINT32 Offset,UINT32 Value)
{
    outpw(REG_PCI_CFGADDR,nSlotIndex+Offset);
    outpw(REG_PCI_CFGDATA,Value);
}


static UINT32 PCIConfig_Read(UINT32 nSlotIndex,UINT32 Offset)
{
    UINT32 Value;
    outpw(REG_PCI_CFGADDR,nSlotIndex+Offset);
    Value = inpw(REG_PCI_CFGDATA);
    return Value;
}


BOOL PCICfgBus(
    PPCI_DEV_INFO pBusInfo,
    UINT32 Bus,
    PUINT32 pSubordinateBus,
    PUINT32 pMemSize,
    PUINT32 pIoSize ,
    PUINT32 pPrefetchMemSize
    );

BOOL PCICfgDevice(
    PPCI_DEV_INFO pBusInfo,
    UINT32 nSlotIndex,
    PPCI_COMMON_CONFIG pCfg,
    PUINT32 pMemSize,
    PUINT32 pIoSize,
    PUINT32 pPrefetchMemSize
    );

VOID PCIInitInfo(PPCI_COMMON_CONFIG pCfg,UINT32 nSlotIndex,PPCI_DEV_INFO pInfo);
INT PCIBusInit(VOID);
INT PCICfg(PPCI_DEV_INFO_EX pinfo);
BOOL PCICfgCheckBARs(
    PPCI_DEV_INFO pInfo,
    PUINT32 pMemSize,
    PUINT32 pIoSize,
    PUINT32 pPrefetchMemSize    
    );
//============================

void PCIGetConfigInfo(PPCI_COMMON_CONFIG pCfg,UINT32 nSlotIndex)
{
    UINT32 cfgdata,i,offset;
    
    cfgdata = PCIConfig_Read(nSlotIndex,0x0);
    pCfg->VendorID = (UINT16) (cfgdata & 0x0000ffff);
    pCfg->DeviceID = (UINT16) ((cfgdata & 0xffff0000) >> 16);
            
    
    cfgdata = PCIConfig_Read(nSlotIndex,0x4);
    
    pCfg->Command = (UINT16)(cfgdata&0x0000ffff);
    pCfg->Status = (UINT16)((cfgdata&0xffff0000)>>16);
    
    cfgdata = PCIConfig_Read(nSlotIndex,0x8);
    pCfg->RevisionID = (UINT8)(cfgdata&0xff);
    pCfg->ProgIf = (UINT8)((cfgdata&0xff00)>>8);
    pCfg->SubClass = (UINT8)((cfgdata&0xff0000)>>16);
    pCfg->BaseClass = (UINT8)((cfgdata&0xff000000)>>24);
    cfgdata = PCIConfig_Read(nSlotIndex,0xc);
    pCfg->CacheLineSize = (UINT8)(cfgdata&0xff);
    pCfg->LatencyTimer = (UINT8)((cfgdata&0xff00)>>8);
    pCfg->HeaderType = (UINT8)((cfgdata&0xff0000)>>16);
    pCfg->BIST = (UINT8)((cfgdata&0xff000000)>>24);
    
    for (i=0,offset=0x10;i<PCI_TYPE0_ADDRESSES;i++,offset=offset+0x4)
    {
        
        
        pCfg->u.type0.BaseAddresses[i] = PCIConfig_Read(nSlotIndex,offset);
    }
    
    pCfg->u.type0.CIS = cfgdata = PCIConfig_Read(nSlotIndex,0x28);
    
    cfgdata = PCIConfig_Read(nSlotIndex,0x2c);
    pCfg->u.type0.SubVendorID = (UINT16)(cfgdata&0xffff);
    pCfg->u.type0.SubSystemID = (UINT16)((cfgdata&0xffff0000)>>16);
    
    cfgdata = PCIConfig_Read(nSlotIndex,0x30);
    pCfg->u.type0.ROMBaseAddress = cfgdata;
    
    cfgdata = PCIConfig_Read(nSlotIndex,0x34);
    pCfg->u.type0.Reserved2[0]=cfgdata;
    pCfg->u.type0.Reserved2[1]=0;
    
    cfgdata = PCIConfig_Read(nSlotIndex,0x3c);
    pCfg->u.type0.InterruptLine = (UINT8)(cfgdata&0xff);
    pCfg->u.type0.InterruptPin = (UINT8)((cfgdata&0xff00)>>8);
    pCfg->u.type0.MinimumGrant = (UINT8)((cfgdata&0xff0000)>>16);
    pCfg->u.type0.MaximumLatency = (UINT8)((cfgdata&0xff000000)>>24);
    
    
}


BOOL PCIScanDevice(PPCI_DEV_INFO_EX pinfo)
{
    UINT32 cfgdata;
    UINT32 device,function,sdevice,sfunction;
    UINT32 addr_index;
    UINT32 nSlotIndex;
    UINT32 Bus;
    UINT32 DeviceID,VendorID;
    PCI_COMMON_CONFIG Cfg;
    BOOL FoundFlag=FALSE;
    
    
    DeviceID = pinfo->pciDevice.DeviceID;
    VendorID = pinfo->pciDevice.VendorID;
    Bus = pinfo->dwBusNumberBase;
    nSlotIndex = pinfo->pciDevice.nSlotIndex;
    sdevice = (nSlotIndex&0xf800)>>11;
    sfunction = (nSlotIndex&0x700)>>8; 
	/*-----  Loop through all device numbers -----*/
    for (device = sdevice; device < PCI_MAX_DEVICES; device++)
    {
        for (function = sfunction; function < PCI_MAX_FUNCTION; function++) 
        {
            addr_index = (Bus<<16) | (device<<11) | (function<<8);
            outpw(REG_PCI_CFGADDR,addr_index);
            cfgdata = inpw(REG_PCI_CFGDATA);
            Cfg.VendorID = (UINT16) (cfgdata & 0x0000ffff);
            Cfg.DeviceID = (UINT16) ((cfgdata & 0xffff0000) >> 16);
            if((Cfg.DeviceID!=DeviceID) || (Cfg.VendorID!=VendorID) || (Cfg.VendorID==0))
            {
                if (function==0)
                    break;
                else
                    continue;
            }
            
            PCIGetConfigInfo(&Cfg,addr_index);
            
            sysprintf("find device ID 0x%x vender ID 0x%x on slot:0x%x\n", Cfg.DeviceID,Cfg.VendorID,addr_index);
            FoundFlag = TRUE;
            pinfo->pciDevice.nSlotIndex = addr_index;
            pinfo->pciDevice.DeviceID = Cfg.DeviceID;
            pinfo->pciDevice.VendorID = Cfg.VendorID;
            if (function == 0 && !(Cfg.HeaderType & PCI_MULTIFUNCTION)) {
                    // Not a multifunction device, continue on to next device
                    break;
                
            }
        }    
    }
	return FoundFlag;
}

BOOL PCIScan(PPCI_DEV_INFO_EX pinfo)
{
    UINT32 cfgdata;
    UINT32 device,function,sdevice,sfunction;
    UINT32 addr_index;
    UINT32 nSlotIndex;
    UINT32 Bus;
    PCI_COMMON_CONFIG Cfg;
    BOOL FoundFlag=FALSE;
    
    Bus = pinfo->dwBusNumberBase;
    nSlotIndex = pinfo->pciDevice.nSlotIndex;
    sdevice = (nSlotIndex&0xf800)>>11;
    sfunction = (nSlotIndex&0x700)>>8; 
	/*-----  Loop through all device numbers -----*/
    for (device = sdevice; device < PCI_MAX_DEVICES; device++)
    {
        for (function = sfunction; function < PCI_MAX_FUNCTION; function++) 
        {
            addr_index = (Bus<<16) | (device<<11) | (function<<8);
            outpw(REG_PCI_CFGADDR,addr_index);
            cfgdata = inpw(REG_PCI_CFGDATA);
            Cfg.VendorID = (UINT16) (cfgdata & 0x0000ffff);
            Cfg.DeviceID = (UINT16) ((cfgdata & 0xffff0000) >> 16);
            if((Cfg.DeviceID==PCI_INVALID_DEVICEID) || (Cfg.VendorID==PCI_INVALID_VENDORID) || (Cfg.VendorID==0))
            {
                if (function==0)
                    break;
                else
                    continue;
            }
            
            PCIGetConfigInfo(&Cfg,addr_index);
            sysprintf("find device ID 0x%x vender ID 0x%x on slot:0x%x\n", Cfg.DeviceID,Cfg.VendorID,addr_index);
            FoundFlag = TRUE;
            pinfo->pciDevice.nSlotIndex = addr_index;
            pinfo->pciDevice.DeviceID = Cfg.DeviceID;
            pinfo->pciDevice.VendorID = Cfg.VendorID;
            if (function == 0 && !(Cfg.HeaderType & PCI_MULTIFUNCTION)) {
                    // Not a multifunction device, continue on to next device
                    break;
            }
        }    
    }
	return FoundFlag;
}



INT PCIBusInit()
{
    int i;
    UINT32 stime;
    
    if (powerup)
        return (ERR_PCI_POWERUP);
    outpw(REG_MFSEL,inpw(REG_MFSEL) &~(3<<2) &~(0xf<<4) &~(3<<11) | (1<<2) | (5<<4) | (3<<11) );//share pin select
    outpw(REG_MFSEL,inpw(REG_MFSEL) | (3<<24) );//configure nIRQ pin 
    outpw(REG_CLKEN,inpw(REG_CLKEN) | (1<<2));//PCI clock on

    stime = get_timer_ticks();
    //reset PCI bus
    outpw (REG_PCI_PCICTR, 0x20C0);
    for (i=0; i<0x7000; i++);
    writew (REG_PCI_PCICTR, 0x20Cf);
    //for (i=0; i<0x7000; i++);
    while(get_timer_ticks()<(stime+50));
    
    powerup=TRUE;
    return 0;
    
}



INT PCIBusDeinit()
{
    //static BOOL powerup=FALSE;
    
    if (!powerup)
        return (ERR_PCI_POWERUP);
    //outpw(REG_MFSEL,inpw(REG_MFSEL) &~(3<<2) &~(0xf<<4) &~(3<<11) | (1<<2) | (5<<4) | (3<<11) | (3<<24) );//share pin select
    //outpw(REG_CLKEN,inpw(REG_CLKEN) &~(1<<2));//PCI clock off
    //outpw(REG_CLKSEL,inpw(REG_CLKSEL) & ~(0x3<<2) | (1<<2) );//CK33 from PLL1
    //outpw(REG_CLKDIV,inpw(REG_CLKDIV) &~(0xf<<4) | (5<<4));//CPI CLOCK = CLK33/6
    outpw(REG_CLKEN,inpw(REG_CLKEN) &~ (1<<2));//PCI clock off
      
    powerup=FALSE;
    return 0;
    
}

INT PCICfg(PPCI_DEV_INFO_EX pinfo)
{
    UINT32 SubordinateBus=0;
    UINT32 MemSize = 0;
    UINT32 IoSize = 0;
    UINT32 addr_index;
    UINT32 i;
    PPCI_DEV_INFO pBusInfo = &(pinfo->pciDevice);
    
    addr_index = pinfo->pciDevice.nSlotIndex;
    for (i=0;i<SLOT_NUM;i++)
    {
        if (g_pciirqmap[i].index==addr_index)
        {
            if (g_pciirqmap[i].matched==TRUE)
            {
                pinfo->pciDevice.nSlotIndex += PCI_DEVICE_OFFSET;
                return FALSE;
            }
            g_pciirqmap[i].matched = TRUE;
            break;
        }
    }
    SubordinateBus = pinfo->dwBusNumberBase;
    PCICfgBus(pBusInfo,0,&SubordinateBus,&MemSize,&IoSize,NULL);
    
    return 0;
}


BOOL PCICfgBus(
    PPCI_DEV_INFO pBusInfo,
    UINT32 Bus,
    PUINT32 pSubordinateBus,
    PUINT32 pMemSize,
    PUINT32 pIoSize ,
    PUINT32 pPrefetchMemSize
    )
{
    UINT32 addr_index;
    PCI_COMMON_CONFIG Cfg;
    BOOL FoundFlag=FALSE;
    UINT32 stime;
    
    
    addr_index = pBusInfo->nSlotIndex;
    
    PCIGetConfigInfo(&Cfg,addr_index);
    if ((Cfg.HeaderType & ~PCI_MULTIFUNCTION) == 0x0)
        PCICfgDevice(pBusInfo,addr_index,&Cfg,pMemSize,pIoSize,pPrefetchMemSize);
    
    #if 1
    if ((Cfg.DeviceID ==0x8139) && (Cfg.VendorID==0x10EC))
    {
        stime = get_timer_ticks();
        while((get_timer_ticks()-stime)<250);
    }
    #endif
	return FoundFlag;
}


BOOL PCICfgDevice(
    PPCI_DEV_INFO pBusInfo,
    UINT32 nSlotIndex,
    PPCI_COMMON_CONFIG pCfg,
    PUINT32 pMemSize,
    PUINT32 pIoSize,
    PUINT32 pPrefetchMemSize
    )
{
    UINT32 Reg;
    UINT32 Pin;
    UINT32 i;
    UINT32 nIRQNum;
    //PCI_DEV_INFO Info;
    PCIInitInfo(pCfg,nSlotIndex,pBusInfo);
    if (!PCICfgCheckBARs(pBusInfo, pMemSize, pIoSize,pPrefetchMemSize)) 
    {
       sysprintf("PCIBUS!PCICfgDevice: Failed PCICfgCheckBARs call\r\n");
       return FALSE;
    }

    // If device not already placed, configure interrupt
    if (!(pCfg->Command & (PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE))) {
        

        Reg = PCIConfig_Read(nSlotIndex, 0x3c);
        Pin = (UINT32)((Reg&0xff00)>>8);

        if (Pin) 
        {
            // Interrupts used, get IRQ
            for (i=0;i<SLOT_NUM;i++)
            {
                if (g_pciirqmap[i].index==nSlotIndex)
                {
                    nIRQNum = g_pciirqmap[i].irqnum;
                    g_pciirqmap[i].g_fnPCICallback = pBusInfo->fnPCICallback;
                    break;
                }
            }

#ifdef ECOS
			cyg_drv_interrupt_create(IRQ_GROUP0, 8, 0, PCI_ISR, 0,
							&pci_interrupt_handle, &pci_interrupt);
    		cyg_drv_interrupt_attach(pci_interrupt_handle);
    		cyg_drv_interrupt_unmask(IRQ_GROUP0);
			/* IRQ group nIRQ0~3 interrupt group enbale */
			outpw(REG_AIC_GEN, inpw(REG_AIC_GEN) | 0xf);  
#else		
            sysEnableGroupInterrupt(1 << nIRQNum);
            sysInstallISR(IRQ_LEVEL_1, IRQ_GROUP0 , (PVOID)PCI_ISR);
            sysEnableInterrupt(IRQ_GROUP0);
#endif
        }
        sysprintf("RequestIrq(0x%x) returns %d\r\n", nSlotIndex, nIRQNum);
    }

    // Set Latency register
    if (pBusInfo->Latency) {
        // Reprogram only if non-zero
    	Reg = PCIConfig_Read(nSlotIndex, 0xc);
    	Reg = (Reg & 0xFFFF00FF) | ((pBusInfo->Latency & 0xFF) << 8);
    	PCIConfig_Write(nSlotIndex, 0xc, Reg);
    }

	// Write command value and reset device status
	if (!(pCfg->Command & (PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE))) {
	    Reg = PCIConfig_Read(nSlotIndex, 0x4);
	    Reg &= 0x7;
	    Reg |= 0xFFFF0000 | (pBusInfo->Command & 0x000003FF);
	    PCIConfig_Write(nSlotIndex, 0x4, Reg);
	}
    
    return TRUE;
}

BOOL PCICfgCheckBARs(
    PPCI_DEV_INFO pInfo,
    PUINT32 pMemSize,
    PUINT32 pIoSize,
    PUINT32 pPrefetchMemSize    
    )
{
    UINT32 i;
    UINT32 Type;
    UINT32 NumberOfRegs;
    UINT32 Offset;
    UINT32 Reg;
    UINT32 Size;
    UINT32 nSlotIndex;
    UINT32 BaseAddress;
    BOOL Placed = FALSE;
    BOOL Prefetchable;
    BOOL SizeFound;
    PPCI_COMMON_CONFIG pCfg = pInfo->pCfg;
    nSlotIndex = pInfo->nSlotIndex;
    // Check to see if device/function already enabled
    #if 1
    if ((pCfg->VendorID==0x1050)&&(pCfg->DeviceID==0x9971))
    {
        // Memory Space
        Reg = pCfg->u.type0.BaseAddresses[0];
        PCIConfig_Write(nSlotIndex,0x10,0xFFFFFFFF);
        BaseAddress = PCIConfig_Read(nSlotIndex,0x10);
        PCIConfig_Write(nSlotIndex, 0x10, Reg);
        Size = ~(BaseAddress & PCI_ADDRESS_MEMORY_ADDRESS_MASK);
        Size +=1;
        if ((g_MemPhyBaseHead+Size)>0xdfffffff)
            return FALSE;
        pInfo->MemBase= g_MemPhyBaseHead;
        pInfo->MemLen = Size;
        PCIConfig_Write(nSlotIndex,0x10,g_MemPhyBaseHead);
        g_MemPhyBaseHead += Size;
        
        //IO Space
        //Size = 0x3e0;
        pInfo->IOBase= 0xe0000000;
        pInfo->IOLen = Size;
        PCIConfig_Write(nSlotIndex,0x14,0);
        //g_IOPhyBaseHead += Size;
        //g_IOLogicBaseHead += Size;
        
        return TRUE;
        
    }
    #endif
    if (pCfg->Command & (PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE)) 
    {
        Placed = TRUE;
    }
    switch (pCfg->HeaderType & ~PCI_MULTIFUNCTION)
    {
        case PCI_DEVICE_TYPE:
            NumberOfRegs = PCI_TYPE0_ADDRESSES;

            break;
        default:
            return FALSE;
    }
    for (i=0,Offset = 0x10;i<NumberOfRegs;i++,Offset+=4)
    {
        Reg = pCfg->u.type0.BaseAddresses[i];
        Type = Reg & PCI_ADDRESS_IO_SPACE;
        Prefetchable = ( Type==0 && (Reg & PCI_ADDRESS_MEMORY_PREFETCHABLE)!=0 && pPrefetchMemSize!=NULL) ;
        if (Placed) 
        {
            // Device already placed and has matching registry entry
            if (Type) {
                // I/O space
                Size = pInfo->IOLen;
                Reg &= PCI_ADDRESS_IO_ADDRESS_MASK;
            } else {
                // Memory space
                Size = pInfo->MemLen;
                Reg &= PCI_ADDRESS_MEMORY_ADDRESS_MASK;
            }
        } else 
        {
            // Device not placed or is placed and has no matching registry entry => Probe hardware for size
            PCIConfig_Write(nSlotIndex,Offset,0xFFFFFFFF);
            BaseAddress = PCIConfig_Read(nSlotIndex,Offset);
            PCIConfig_Write(nSlotIndex, Offset, Reg);

            if (Type) {
                // IO space
                // Re-adjust BaseAddress if upper 16-bits are 0 (allowable in PCI 2.2 spec)
                if (((BaseAddress & PCI_ADDRESS_IO_ADDRESS_MASK) != 0) && ((BaseAddress & 0xFFFF0000) == 0)) {
                    BaseAddress |= 0xFFFF0000;
                }
                
                Size = ~(BaseAddress & PCI_ADDRESS_IO_ADDRESS_MASK);
                Reg &= PCI_ADDRESS_IO_ADDRESS_MASK;

                SizeFound = TRUE;
            } else {
                // Memory space
                if ((Reg & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_20BIT) {
                    // PCI 2.2 spec no longer supports this type of memory addressing
                    sysprintf("PCIBUS!PCICfgCheckBARs: 20-bit addressing not supported\r\n");
                    return FALSE;
                }
                
                // Re-adjust BaseAddress if upper 16-bits are 0 (allowed by PCI 2.2 spec)
                if (((BaseAddress & PCI_ADDRESS_MEMORY_ADDRESS_MASK) != 0) && ((BaseAddress & 0xFFFF0000) == 0)) {
                    BaseAddress |= 0xFFFF0000;
                }
                
                Size = ~(BaseAddress & PCI_ADDRESS_MEMORY_ADDRESS_MASK);
                Reg &= PCI_ADDRESS_MEMORY_ADDRESS_MASK;
            }
            // Check that the register has a valid format; it should have consecutive high 1's and consecutive low 0's
            SizeFound = (BaseAddress != 0) && (BaseAddress != 0xFFFFFFFF) && (((Size + 1) & Size) == 0);
            // Check that the register has a valid format; it should have consecutive high 1's and consecutive low 0's
            Size +=1;
        }

        if (SizeFound)
        {
            if (Type)//IO space 
            {
                if ((g_IOPhyBaseHead+Size)>0xffffffff)
                    return FALSE;
                pInfo->IOBase = g_IOPhyBaseHead;
                pInfo->IOLen = Size;
                PCIConfig_Write(nSlotIndex,Offset,g_IOLogicBaseHead);
                g_IOPhyBaseHead += Size;
                g_IOLogicBaseHead +=Size;
                //g_IOAllocated += Size;
                
            }
            
            else//Memory space
            {
                if ((g_MemPhyBaseHead+Size)>0xdfffffff)
                    return FALSE;
                pInfo->MemBase= g_MemPhyBaseHead;
                pInfo->MemLen = Size;
                PCIConfig_Write(nSlotIndex,Offset,g_MemPhyBaseHead);
                g_MemPhyBaseHead += Size;
               // g_MemAllocated += Size;
                
            }
            
        }
        else if (Size!=0)
        {
            sysprintf("check size format invalid\n");
            continue;
        }
    }

    return TRUE;
}


VOID PCIInitInfo(PPCI_COMMON_CONFIG pCfg,UINT32 nSlotIndex,PPCI_DEV_INFO pInfo)
{
    pInfo->nSlotIndex = nSlotIndex;
    pInfo->pCfg = pCfg;
    //pInfo->MemBase = 0;
    //pInfo->MemLen = 0;
    //pInfo->IoBase = 0;
    //pInfo->IoLen = 0;
    //pInfo->Command = 0;
    //pInfo->Latency = 0;
    //pInfo->SecondaryLatency = 0;
}

